package com.ruoyi.express.third;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.express.third.exception.ThirdApiError;
import com.ruoyi.express.third.exception.ThirdApiException;
import com.ruoyi.express.third.util.HttpClientParam;
import com.ruoyi.express.third.util.HttpClientUtil;
import com.ruoyi.express.third.util.HttpLibs;
import com.ruoyi.express.third.util.HttpMethod;
import com.ruoyi.express.third.util.ResultDto;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author chenck
 * @date 2019/3/9 14:18
 */
public class BaiduSupport {

    private static Logger LOGGER = LoggerFactory.getLogger(BaiduSupport.class);

    public static <T extends BaiduResult> T call(BaiduInput<T> input) {
        T result = null;
        StringBuilder msgPrefix = new StringBuilder("[Baidu]");
        try {
            if (null == input) {
                throw new ThirdApiException(ThirdApiError.RES_PAY_PARAM_ERROR, "input param must not null");
            }
            msgPrefix.append("[").append(input.getClass().getSimpleName()).append("]");
            if (StringUtils.isBlank(input.getUrl())) {
                throw new ThirdApiException(ThirdApiError.RES_PAY_PARAM_ERROR, "api url must not null");
            }

            // URL参数构建
            String requestUrl = HttpLibs.buildRequestURL(input.getUrlParamMap(), input.getUrl());
            LOGGER.info("{}[requestUrl]{}", msgPrefix, requestUrl);

            // post请求方式则构建json数据
            HttpEntity entity = null;
            if (HttpMethod.POST.name().equals(input.getMethod())) {
                List<BasicNameValuePair> reqDataList = new ArrayList<>();
                String requestData = JSON.toJSONString(input);
                LOGGER.info("{}[requestData]{}", msgPrefix, requestData);
                JSONObject map = JSON.parseObject(requestData);
                for(Map.Entry<String, Object> entry : map.entrySet()){
                    if(null == entry.getValue()){
                        continue;
                    }
                    reqDataList.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                entity = new UrlEncodedFormEntity(reqDataList, Consts.UTF_8);
            }

            result = (T) input.getResultClazz().newInstance();

            HttpClientParam reqParam = HttpClientParam.create().setRequesturi(requestUrl)
                    .setEntity(entity)
                    .setMethod(HttpMethod.POST.name());

            RequestConfig.Builder builder = RequestConfig.custom();
            if (StringUtils.isNotBlank(input.getProxyHost()) && input.getProxyPort() > 0) {
                builder.setProxy(new HttpHost(input.getProxyHost(), input.getProxyPort()));
            }
            ResultDto resultDto = HttpClientUtil.invoke(reqParam, builder.build());
            LOGGER.info("{}[responseData]{}", msgPrefix, com.alibaba.fastjson.JSON.toJSONString(resultDto));

            // 判断本次请求执行的结果（非业务结果）
            if (resultDto.isFail()) {
                throw new ThirdApiException(ThirdApiError.RES_OTHER_ERROR, "[接口调用异常]" + resultDto.getRetMsg());
            }
            if (resultDto.isTimeout()) {
                throw new ThirdApiException(ThirdApiError.RES_TIME_OUT_ERROR, "[接口调用超时]" + resultDto.getRetMsg());
            }

            String responseJson = resultDto.getBizDataObj().toString();
            if (StringUtils.isBlank(responseJson)) {
                throw new ThirdApiException(ThirdApiError.RES_PAY_ERROR, "baidu api return empty");
            }

            result = (T) JSON.parseObject(responseJson, result.getClass());

            // 判断业务方的执行结果，0表示成功，非0表示失败此字段是通信标识
            // 判断业务结果
            if (StringUtils.isNotBlank(result.getError())) {
                throw new ThirdApiException(result.getError(), result.getError_description());
            }

        } catch (ThirdApiException e) {
            LOGGER.error(msgPrefix.toString(), e);
            throw new ThirdApiException(e);
        } catch (Exception e) {
            LOGGER.error(msgPrefix.toString(), e);
            throw new ThirdApiException(ThirdApiError.SYSTEM_ERROR, e.getMessage());
        }
        if (null == result) {
            throw new ThirdApiException(ThirdApiError.SYSTEM_ERROR, "系统繁忙");
        }
        return result;
    }

}
